#include <iostream>
#include <algorithm>

using namespace std;

/*
[外部变量访问方式说明符](参数)mutable noexcept/throw()->返回值类型
{
    函数体;
};
*/


/*
1) [外部变量方位方式说明符]
[ ] 方括号用于向编译器表明当前是一个 lambda 表达式，其不能被省略。在方括号内部，可以注明当前 lambda 函数的函数体中可以使用哪些“外部变量”。
所谓外部变量，指的是和当前 lambda 表达式位于同一作用域内的所有局部变量。

2) (参数)
和普通函数的定义一样，lambda 匿名函数也可以接收外部传递的多个参数。和普通函数不同的是，如果不需要传递参数，可以连同 () 小括号一起省略；

3) mutable
此关键字可以省略，如果使用则之前的 () 小括号将不能省略（参数个数可以为 0）。默认情况下，对于以值传递方式引入的外部变量，不允许在 lambda 表达式内部修改它们的值（可以理解为这部分变量都是 const 常量）。而如果想修改它们，就必须使用 mutable 关键字。

注意，对于以值传递方式引入的外部变量，lambda 表达式修改的是拷贝的那一份，并不会修改真正的外部变量；

4) noexcept/throw()
可以省略，如果使用，在之前的 () 小括号将不能省略（参数个数可以为 0）。默认情况下，lambda 函数的函数体中可以抛出任何类型的异常。而标注 noexcept 关键字，则表示函数体内不会抛出任何异常；使用 throw() 可以指定 lambda 函数内部可以抛出的异常类型。

值得一提的是，如果 lambda 函数标有 noexcept 而函数体内抛出了异常，又或者使用 throw() 限定了异常类型而函数体内抛出了非指定类型的异常，这些异常无法使用 try-catch 捕获，会导致程序执行失败（本节后续会给出实例）。

5) -> 返回值类型
指明 lambda 匿名函数的返回值类型。值得一提的是，如果 lambda 函数体内只有一个 return 语句，或者该函数返回 void，则编译器可以自行推断出返回值类型，此情况下可以直接省略-> 返回值类型。

6) 函数体
和普通函数一样，lambda 匿名函数包含的内部代码都放置在函数体中。该函数体内除了可以使用指定传递进来的参数之外，还可以使用指定的外部变量以及全局范围内的所有全局变量。

需要注意的是，外部变量会受到以值传递还是以引用传递方式引入的影响，而全局变量则不会。换句话说，在 lambda 表达式内可以使用任意一个全局变量，必要时还可以直接修改它们的值。
其中，红色标识的参数是定义 lambda 表达式时必须写的，而绿色标识的参数可以省略。

*/


/*
外部变量格式	            功能
[]	                空方括号表示当前 lambda 匿名函数中不导入任何外部变量。
[=]	                只有一个 = 等号，表示以值传递的方式导入所有外部变量；
[&]	                只有一个 & 符号，表示以引用传递的方式导入所有外部变量；
[val1,val2,...]	    表示以值传递的方式导入 val1、val2 等指定的外部变量，同时多个变量之间没有先后次序；
[&val1,&val2,...]	表示以引用传递的方式导入 val1、val2等指定的外部变量，多个变量之间没有前后次序；
[val,&val2,...]	    以上 2 种方式还可以混合使用，变量之间没有前后次序。
[=,&val1,...]	    表示除 val1 以引用传递的方式导入外，其它外部变量都以值传递的方式导入。
[this]	            表示以值传递的方式导入当前的 this 指针。
*/

static void test1()
{
    int num[4] {4, 3, 2, 1};

    sort(num, num + 4, [=](int x, int y){return x < y;});

    for (int n : num)
        cout<<n<<" ";
    cout<<endl;
}

static void test2()
{
    auto display = [](int a, int b){ cout<<a<<" "<<b<<endl;};
    display(10, 20);
}


static void test3()
{
    auto except = []()throw(int) { throw 10; };

    try{
        except();
    }
    catch(int value){
        cout<<"catch: "<<value<<endl;
    }
}

int main(int argc, char * argv [ ])
{
    test3();
    return 0;
}

